using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
using Sedna.API.Security;
using Sedna.API.Session;
using Sedna.API.Support;

namespace Sedna.API.Session
{
    public class SessionTracker
    {
        private IDictionary<IToken, ISession> sessions;
        private Thread trackerThread;
        private volatile bool isStopping = false;
        private TimeSpan TRACKING_INTERVAL = new TimeSpan(0,0,1);
        private TimeSpan timeout;

               
        
//        public void SetSession(IToken sessionKey, ISession value)
//        {
//            lock (sessions)
//            {
//                sessions[sessionKey] = value;
//            }
//        }
        
        
        public SessionTracker(TimeSpan timeout)
        {
            this.sessions = new Dictionary<IToken, ISession>();
            this.timeout = timeout;
            trackerThread = new Thread(this.Track);
        }
        
        ~SessionTracker()
        {
            StopTracking();
            //Is it dangerous?
            trackerThread.Join();
        }

        public ISession Get(IToken sessionKey)
        {
            if (sessionKey == null) return null;
            lock (sessions)
            {
                ISession session = null;
                sessions.TryGetValue(sessionKey, out session);
                if (session == null)
                {
                    return null;
                }
                session.Timestamp = DateTime.Now;
                return session;
            }
        }
        
        public void Add(ISession session)
        {
            lock (sessions)
            {
                sessions.Add(session.SessionKey, session);
            }
        }
        
        public void Remove(IToken token)
        {
            lock (sessions)
            {
                sessions.Remove(token);
            }
        }
        
        public void StartTracking()
        {
            if (isStopping)
            {
                trackerThread.Join();
            }
            trackerThread.Start();
        }
        
        public void StopTracking()
        {
            isStopping = true;    
        }
                
        private void Track()
        {
            while (!isStopping)
            {
                lock(sessions)
                {
                    IList<ISession> sessionsToDestroy = new List<ISession>();
                    foreach (KeyValuePair<IToken, ISession> pair in sessions)
                    {
                        if ((DateTime.Now - pair.Value.Timestamp)>timeout)
                        {
                            sessionsToDestroy.Add(pair.Value);   
                        }    
                    }
                    foreach(ISession session in sessionsToDestroy)
                    {
                        sessions.Remove(session.SessionKey);
                    }
                }
                
                Thread.Sleep(TRACKING_INTERVAL);
            }
            isStopping = false;
        }

    }
}

